package mutris.server;

import java.net.InetSocketAddress;
import java.util.concurrent.Executors;

import org.jboss.netty.bootstrap.ServerBootstrap;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
import org.jboss.netty.handler.codec.frame.DelimiterBasedFrameDecoder;
import org.jboss.netty.handler.codec.frame.Delimiters;

/**
 * Classe ServerConnection
 * 
 * Cette classe fait interface avec les package NIO Socket de Netty
 * et gère la connexion distante proprement parlant.
 * 
 * @author Yanick Rochon, Cedric Deschênes, Jean-Philippe Courchesne
 *
 */

public class ServerConnection {

	static private final int ASYNC_TIMEOUT = 1000;
	static public final int MAX_FRAME_LENGTH = 1024;
	
	private ServerBootstrap serverBootstrap;
	private Channel serverChannel;
	
	
	public ServerConnection() {
		
		// Configure the server
		serverBootstrap = new ServerBootstrap(
				new NioServerSocketChannelFactory(
						Executors.newCachedThreadPool(),
						Executors.newCachedThreadPool()));

		// Set up the pipeline factory
		serverBootstrap.setPipelineFactory(new ChannelPipelineFactory() {
			public ChannelPipeline getPipeline() throws Exception {
				return Channels.pipeline(
						new DelimiterBasedFrameDecoder(MAX_FRAME_LENGTH, Delimiters.lineDelimiter()),
						new CommandHandler()
				);
			}
		});
		
	}
	
	public boolean setupServer(ServerSettings settings) {
		if (isServerBound()) {
			throw new IllegalStateException();
		}
		
		// Start the connection attempt.
		serverChannel = serverBootstrap.bind(new InetSocketAddress(settings.getServerPort()));
		
		return serverChannel.isBound();
	}
	
	public boolean isServerBound() {
		if (((serverChannel == null) || !serverChannel.isBound())) {
			return false;
		}
		
		return true;
	}
	
	public boolean shutdownServer() {
		if (serverChannel != null) {
			serverChannel.unbind().awaitUninterruptibly(ASYNC_TIMEOUT);
			serverChannel = null;
		}
		return !isServerBound();
	}


}